import json
import logging

from django.core.exceptions import PermissionDenied
from django.shortcuts import HttpResponse, render
from django.http import JsonResponse, Http404
from django.views import View
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from django.db.models import Q

from article_manager.models import Article, Category as CategoryModel
from .utils import translate_zh2en_mark, prettify_html, delete_html_tag
from bcm_auth.models import User
from site_maps import post_urls_to_baidu
from django.forms import model_to_dict

LOG = logging.getLogger(__name__)


class Index(DetailView):
    object = object()
    template_name = 'index/index.html'
    extra_context = {}

    def get_context_data(self, **kwargs):
        articles = Article.objects.order_by('-update_time')[:10]

        if not articles:
            return self.extra_context

        self.extra_context = {}
        self.extra_context.setdefault('articles', [])

        for article in articles:
            self.extra_context['articles'].append(article.to_dict())

        return self.extra_context

    def get(self, req, *args, **kwargs):
        context = self.get_context_data(object=self.object)
        return render(req, self.template_name, context=context)


class AuthorArticle(ListView):
    template_name = 'article_list.html'

    context_object_name = 'articles'
    model = Article
    ordering = '-update_time'
    url_kwarg = 'author_name'
    username = ''
    # 判断是否为其它用户访问
    is_other_user = False
    extra_context = {}
    # 翻页配置
    paginate_by = 15

    def get(self, request, *args, **kwargs):
        self.is_other_user = False
        # 获取URL当中的用户名，查看作者文章
        self.username = kwargs.get(self.url_kwarg, None)
        if request.user.username != self.username:
            self.is_other_user = True
        return super(AuthorArticle, self).get(request, *args, **kwargs)

    def get_context_data(self, *, object_list=None, **kwargs):
        object_list = self.object_list.filter(Q(author_detail__username=self.username) & Q(delete=False))
        self.extra_context['paginator_range'] = range(1, self.paginate_by + 1)
        return super(AuthorArticle, self).get_context_data(object_list=object_list)

    def get_template_names(self):
        if self.is_other_user:
            return ['others_article_list.html']
        return super(AuthorArticle, self).get_template_names()

    def post(self, req, author_name):
        """
        push 推送的文章列表
        :param req:
        :param article_id:
        :return:
        """
        data = json.loads(req.body.decode('utf8'))
        pushs = data.get('push', None)
        if pushs:
            host = req.get_host()
            return JsonResponse(self._push_url(host, pushs))

    def _push_url(self, host, urls):
        data = "\n".join(host + "/article_detail/" + str(url) + ".html" for url in urls)
        return post_urls_to_baidu(data)


class ArticleCategory(ListView):
    template_name = 'article_category.html'

    model = Article
    ordering = '-update_time'
    context_object_name = 'articles'

    url_agrs = {}
    extra_context = {}
    url_category_key = 'category'

    paginate_by = '15'

    object_list = object()

    categories = CategoryModel.objects.filter(is_nav=True).values()

    def get_context_data(self, *, object_list=None, **kwargs):
        category = self.url_agrs.get(self.url_category_key, 'all')
        if category == 'all':
            object_list = self.object_list.filter(Q(hide=False) & Q(delete=False))
        else:
            object_list = self.object_list.filter(Q(category__en_assortment=category) \
                                                  & Q(hide=False) & Q(delete=False))

        # 文章分类下没有文章,会发生错误
        try:
            category = object_list.first().category_name
        except AttributeError as exc:
            category = ''
            LOG.error(msg=str(exc))
        finally:
            self.extra_context['path_name'] = '所有文章' if category == 'all' else category

        self.extra_context['categories'] = self.categories
        return super().get_context_data(object_list=object_list)

    def get(self, request, *args, **kwargs):
        self.url_agrs = kwargs
        self.object_list = self.get_queryset()
        context = self.get_context_data()
        return render(request, self.template_name, context=context)


class Edit(View):
    waite_dict = {}

    def get(self, req, *args, **kwargs):
        categories_obj = CategoryModel.objects.all()
        categories = [model_to_dict(category) for category in categories_obj]
        md = req.GET.get('md', False)
        template_name = 'article_edit.html'
        if md:
            template_name = 'article_edit_md.html'

        if not req.user.username:
            raise PermissionDenied
        article_id = self.check_kwargs(**kwargs)
        context = {'article_id': 0}
        if article_id and article_id > 0:
            art = Article.objects.filter(Q(id=article_id)).first()
            if art.md:
                template_name = 'article_edit_md.html'
            context['title'] = art.title
            context['content'] = art.content
            context['tag'] = art.tag
            context['article_id'] = article_id
            context['category'] = [art.category_id, art.category.assortment]
        context['categories'] = categories
        return render(req, template_name, context=context)

    def post(self, req, *args, **kwargs):
        resp = {}

        article_id = self.check_kwargs(**kwargs)

        req_user_id = req.user.id

        if not req_user_id:
            resp['message'] = "请登陆后操作"
            return HttpResponse(json.dumps(resp), content_type="application/json")

        art = Article.objects.filter(id=article_id).first()

        if art:
            article_user_id = art.author_detail.id
        else:
            article_user_id = req_user_id

        if not article_user_id or article_user_id != req_user_id:
            resp['message'] = "你没有操作该文章的权限，你可能没有登陆或者试图修改别人的文章"
            return HttpResponse(json.dumps(resp), content_type="application/json")
        context = req.body
        if isinstance(context, bytes):
            context = context.decode(encoding='utf8')
        article_post = json.loads(context)

        title = article_post.get('article_title', None)
        content = article_post.get('editor_content', None)
        tag = article_post.get('article_tag', None)
        category = article_post.get('article_category', None)
        md = article_post.get('md', False)

        if not content or not title or not tag or not category:
            resp['message'] = "标题、正文、文章分类或标签不能为空"
            return HttpResponse(json.dumps(resp), content_type="application/json")
        if isinstance(category, str):
            category_id = int(category)

        # 摘要为去除html标签的正文
        summary = delete_html_tag(content)

        if not summary or len(summary) <= 100:
            resp['message'] = "正文内容不能少于100字"
            return HttpResponse(json.dumps(resp), content_type="application/json")

        tag = translate_zh2en_mark(article_post['article_tag'])

        if article_id and article_id > 0:
            art = Article.objects.get(Q(id=article_id) & Q(author_detail_id=req_user_id))
            art.title = title
            art.summary = summary[:300]
            art.category_id = category_id
            art.content = prettify_html(content)
            art.save()
            resp['message'] = '文章《' + title + '》修改成功'

        if not article_id:
            Article.objects.create \
                (title=title, content=content, author_detail_id=req_user_id, tag=tag, summary=summary[:300],
                 category_id=category_id, md=md)
            resp['message'] = '文章《' + title + '》提交成功'

            last_art = Article.objects.filter(delete=False,
                                              author_detail_id=req_user_id,
                                              title=title
                                              ).order_by('-update_time').first()
            resp['article_id'] = last_art.id
            resp['action'] = 'submit'
        return HttpResponse(json.dumps(resp), content_type="application/json")

    def check_kwargs(self, **kwargs):
        article_id = kwargs['article_id']
        if not isinstance(article_id, int):
            article_id = int(article_id)
        return article_id


class ArticleDetail(DetailView):
    template_name = 'article_detail.html'
    pk_url_kwarg = 'article_id'
    context_object_name = 'article'
    model = Article
    object = object()

    def get_object(self, queryset=None):
        obj = super(ArticleDetail, self).get_object()
        if obj and obj.delete:
            raise Http404('文章《%s》已经被删除' % obj.title)
        return obj

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        del context['object']
        del context['view']
        return render(request, self.template_name, context=context)
